import Icons from '@app-nextmesh/Icons';
import { Tree, TreeProps } from 'antd';
import { BasicDataNode } from 'antd/es/tree';
import React, { ComponentType, useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
import { ITreeNode, TreeNodeType } from '../types';

const StyledTree: ComponentType<TreeProps<ITreeNode & BasicDataNode>> = styled(
  Tree<ITreeNode & BasicDataNode>,
)`
  background: transparent;

  & .ant-tree-node-content-wrapper {
    display: flex;

    &:hover {
      background-color: #c1c0ee;
    }
  }

  /* 节点文字不换行 */
  & .ant-tree-node-content-wrapper {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 180px;
  }

  /* 修改被选中节点的颜色 */
  &
    .ant-tree-node-content-wrapper:not(
      .ant-tree-node-disabled
    ).ant-tree-node-selected {
    color: #fff;
    background-color: #4e4ede;
  }
`;

const idType: string[] = [
  TreeNodeType.Components,
  TreeNodeType.Meshes,
  TreeNodeType.MeshControl,
  TreeNodeType.Collections,
  TreeNodeType.Simulations,
  TreeNodeType.Tasks,
  TreeNodeType.PostProcess,
];
const withNodeTitleRenderer = (
  handleDoubleClick: (data: ITreeNode) => void,
) => {
  return (nodeData: ITreeNode & BasicDataNode) => {
    return (
      <TitleRender
        titleData={nodeData}
        onDoubleClick={handleDoubleClick}
      />
    );
  };
};
const TitleRender = ({
  titleData,
  onDoubleClick,
}: {
  titleData: ITreeNode & BasicDataNode;
  onDoubleClick: (data: ITreeNode) => void;
}) => {
  const titleElement = useRef<HTMLSpanElement>(null);

  useEffect(() => {
    const nodeElement = titleElement.current.parentElement?.parentElement;

    const handleDoubleClick = () => {
      onDoubleClick?.(titleData);
    };

    nodeElement?.addEventListener('dblclick', handleDoubleClick);

    return () => {
      nodeElement?.removeEventListener('dblclick', handleDoubleClick);
    };
  }, [titleData, onDoubleClick]);
  return (
    <span
      ref={titleElement}
      style={{
        fontWeight: idType.includes(titleData.id) ? 'bold' : '',
      }}>
      {titleData.label}
    </span>
  );
};
export interface ITreeProps {
  initialData: ITreeNode[];
  selection?: string;
  onContextMenu?: (
    event: React.MouseEvent<Element, MouseEvent>,
    data: ITreeNode,
  ) => void;
  onActivate?: (data: ITreeNode) => void;
  onDoubleClick?: (data: ITreeNode) => void;
}
export default function ArboristTree(props: ITreeProps) {
  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]); // 默认展开指定的树节点
  const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]); // 设置选中的树节点
  useEffect(() => {
    if (props?.selection == undefined) {
      return;
    }
    const selectionId = [props.selection];
    setSelectedKeys(selectionId);
  }, [props?.selection]);
  useEffect(() => {
    if (!props?.initialData) {
      return;
    }
    const keys = getKeys(props.initialData);
    setExpandedKeys(keys);
  }, [props?.initialData, selectedKeys]);
  const getKeys = (nodes: ITreeNode[]) => {
    const keys = [];
    nodes.forEach((item) => {
      keys.push(item.id);
      if (Array.isArray(item.children)) {
        keys.push(...getKeys(item.children));
      }
    });
    return keys;
  };
  // 数据格式化
  const flattenArray = (nodes: ITreeNode[]) =>
    nodes.map((item) => {
      if (Array.isArray(item.children)) {
        item.children = flattenArray(item.children);
      }
      const icon = (
        <Icons
          name={item.iconName}
          defaultName='Icon_Default'
        />
      );
      return {
        ...item,
        title: item.label,
        key: item.id,
        icon,
      };
    });
  return (
    <StyledTree
      titleRender={withNodeTitleRenderer(props.onDoubleClick)}
      blockNode
      defaultExpandAll
      defaultExpandedKeys={expandedKeys}
      showIcon
      treeData={flattenArray(props.initialData)}
      onSelect={(_, e) => {
        setSelectedKeys([e.node.key]);
        props.onActivate?.(e.node);
      }}
      onRightClick={(info) => {
        props.onContextMenu?.(info.event, info.node);
      }}
      showLine={{ showLeafIcon: false }}
      selectedKeys={selectedKeys}
    />
  );
}
